{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### <b>Final Project code:</b>\n",
    "<br> Sotiris Evangelou 2159\n",
    "<br> Lefteris Chatziefremidis 2209\n",
    "<br> Kostas Kalais 2146"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Main Bash script (Pipeline)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#!/bin/bash\n",
    "sudo go run capture.go $(echo -e \"import netifaces\\nprint(netifaces.gateways()['default'][netifaces.AF_INET][1])\" | python3) | \n",
    "sudo python writefile.py | \n",
    "sudo python outputfields.py | \n",
    "python main.py\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Capture.go"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "func main(){\n",
    "  if(!checkForArguments()){\n",
    "    fmt.Println(\"[ERROR]: Give the correct argument.\")\n",
    "    return\n",
    "  }\n",
    "  // Retrieve the interface\n",
    "  device := os.Args[1]  \n",
    "\n",
    "  // Open output pcap file and write header \n",
    "  f := os.Stdout\n",
    "\tw := pcapgo.NewWriter(f)\n",
    "\tw.WriteFileHeader(1024, layers.LinkTypeEthernet)\n",
    "\tdefer f.Close()\n",
    "  \n",
    "  //Open device\n",
    "  handle,err = pcap.OpenLive(device,1024,promiscuous,timeout)\n",
    "\n",
    "  if err != nil{\n",
    "    fmt.Println(err)\n",
    "    return\n",
    "  }\n",
    "  defer handle.Close()\n",
    "\n",
    "  // Use the handle as a packet source to process all packets\n",
    "  packetSource := gopacket.NewPacketSource(handle,handle.LinkType())\n",
    "  for packet := range packetSource.Packets(){\n",
    "    //printPacketInfo(packet) \n",
    "\t  w.WritePacket(packet.Metadata().CaptureInfo, packet.Data())\n",
    "    packetCount++\n",
    "    \n",
    "    //if packetCount > 10000{\n",
    "    //  break\n",
    "    //}\n",
    "  }  \n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Writefile.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "while True:\n",
    "  os.system(\"argus -w -\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Outputfields.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "while True:\n",
    "  os.system(\"ra -r - -L0 -c ,  -s -Z +dport +ltime +dur +proto +state +spkts +dpkts +rate +sttl +dttl +sload +dload +sintpkt +dintpkt +sjit +djit +swin +stcpb +dtcpb +tcprtt +smeansz +dmeansz +trans\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Main.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "import keras\n",
    "from keras.models import model_from_json\n",
    "from onlyLabelsPrepare import transform_to_nominal\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from os import path"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Load the Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_model(name):\n",
    "    #load json and create model\n",
    "    json_file = open(name+\".json\",\"r\")\n",
    "    loaded_model_json = json_file.read()\n",
    "    json_file.close()\n",
    "    model = model_from_json(loaded_model_json)\n",
    "    model.load_weights(name+\".h5\")\n",
    "    model.compile(loss='mean_squared_error', optimizer='adam')\n",
    "    print(\"Loaded model...\")\n",
    "    return model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Additional Features algorithms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ct_state_ttl(sttl,dttl,state):\n",
    "  ct_state = \"0\"\n",
    "  if sttl == ('62' or '63' or '254' or '255') and dttl == ('252' or '253') and state == 'FIN':\n",
    "    ct_state = \"1\"\n",
    "  elif sttl == ('0' or '62' or '254') and dttl == '0' and state =='INT':\n",
    "    ct_state = \"2\"\n",
    "  elif sttl == ('62' or '254') and dttl == ('60' or '252' or '253') and state =='CON':\n",
    "    ct_state = \"3\"\n",
    "  elif sttl == '254' and dttl == '252' and state == 'ACC' :\n",
    "    ct_state = \"4\"\n",
    "  elif sttl == '254' and dttl == '252' and state == 'CLO':\n",
    "    ct_state = \"5\"\n",
    "  elif sttl == '254' and dttl == '0' and state == 'REQ':\n",
    "    ct_state = \"6\"\n",
    "  else:\n",
    "    ct_state = \"0\"\n",
    "  \n",
    "  return ct_state\n",
    "\n",
    "def define_service(dstport):\n",
    "  if dstport == \"https\" :\n",
    "    service = \"https\"\n",
    "    dstport = \"443\"\n",
    "  elif dstport == \"http\":\n",
    "    service = \"http\"\n",
    "    dstport = \"80\"\n",
    "  elif dstport == \"ftp\":\n",
    "    service = \"ftp\"\n",
    "    dstport = \"21\"\n",
    "  elif dstport == \"domain\":\n",
    "    service = \"domain\"\n",
    "    dstport = \"53\"\n",
    "  elif dstport == \"mdns\":\n",
    "    service = \"dns\"\n",
    "    dsport = \"5353\"\n",
    "  elif dstport == \"netbios-dgm\":\n",
    "    service = \"netbios-dgm\"\n",
    "    dstport = \"138\"\n",
    "  elif dstport == \"smtp\":\n",
    "    service = \"smtp\"\n",
    "    dstport = \"25\"\n",
    "  elif dstport == \"snmp\":\n",
    "    service = \"snmp\"\n",
    "    dstport = \"161\"\n",
    "  elif dstport == \"ftp-data\":\n",
    "    service = \"ftp-data\"\n",
    "    dstport = \"20\"\n",
    "  elif dstport == \"ssh\":\n",
    "    service = \"ssh\"\n",
    "    dstport = \"22\"\n",
    "  elif dstport == \"dhcp\":\n",
    "    service = \"dhcp\"\n",
    "    dstport = \"546\"\n",
    "  elif dstport == \"irc\":\n",
    "    service = \"irc\"\n",
    "    dstport = \"194\"\n",
    "  elif dstport == \"pop3\":\n",
    "    service = \"pop3\"\n",
    "    dstport = \"995\"\n",
    "  elif dstport == \"radius\":\n",
    "    service = \"radius\"\n",
    "    dstport = \"1812\"\n",
    "  elif dstport == \"ssl\":\n",
    "    service = \"ssl\"\n",
    "    dstport = \"443\" \n",
    "  else :\n",
    "    service = \"-\"\n",
    "\n",
    "  return dstport,service\n",
    "\n",
    "def is_ftp_login(service):\n",
    "  if service == 'ftp':\n",
    "    return 1\n",
    "  else: \n",
    "    return 0\n",
    "\n",
    "def basic_tokens(line):\n",
    "  tokens = line.split(\",\")\n",
    "  # Retrieve the service\n",
    "  srcip = tokens[3]\n",
    "  srcport = tokens[4]\n",
    "  dstip = tokens[6]\n",
    "  dstport = tokens[7]\n",
    "  res_bd_len = tokens[9]\n",
    "  ltime = tokens[12]\n",
    "  \n",
    "  # Retrieve the service \n",
    "  dstport,service = define_service(dstport)\n",
    " \n",
    "  if service == \"http\" or service == \"https\":\n",
    "    res_bd_len = tokens[9]\n",
    "  else:\n",
    "    res_bd_len = \"0\"\n",
    "\n",
    "  # Get the other arguments\n",
    "  tokens = tokens[13:]\n",
    "  tokens.insert(2,service)\n",
    "  \n",
    "  # Replace '' with 0 and remove \\n \n",
    "  for i in range(len(tokens)):\n",
    "    if tokens[i] == \"\":\n",
    "      tokens[i] = \"0\"\n",
    "    elif \"\\n\" in tokens[i]:\n",
    "      tokens[i] = tokens[i].replace(\"\\n\",\"\")\n",
    "\n",
    "  # insert ct_state_ttl\n",
    "  ct_state_t = ct_state_ttl(tokens[7],tokens[8],tokens[3])\n",
    "  tokens.insert(len(tokens)+1,ct_state_t)\n",
    "  \n",
    "  # ftp login\n",
    "  tokens.insert(len(tokens)+1,is_ftp_login(service))\n",
    "\n",
    "  return tokens,srcip,srcport,dstip,dstport,ltime,res_bd_len\n",
    "\n",
    "\n",
    "def ct_srv_src(curIp,curService,nextIp,nextService,ct_srv):\n",
    "  if curIp == nextIp and curService == nextService:\n",
    "    ct_srv+=1\n",
    "  elif curIp != nextIp and curService != nextService:\n",
    "    ct_srv= 1\n",
    "  else:\n",
    "    ct_srv = 0\n",
    "  return ct_srv\n",
    "\n",
    "\n",
    "def ct_flw_http_mthd(srcip,dstip,sport,dstport,nextSrcip,nextDstip,nextSport,nextDsport,method,ct_flow):\n",
    "  if srcip == nextSrcip and dstip == nextDstip and sport == nextSport and dstport == nextDsport and (method!=\"-\" ): \n",
    "    ct_flow +=1\n",
    "  else: \n",
    "    ct_flow = 0\n",
    "  return ct_flow  \n",
    "\n",
    "\n",
    "def ct_dst_ltm(dstIp,ltime,nextDstIp,nextLtime,ct_dst):\n",
    "  if dstIp == nextDstIp and ltime == nextLtime:\n",
    "    ct_dst += 1\n",
    "  else:\n",
    "    ct_dst = 1\n",
    "  return ct_dst    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Running the model on the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def multilayer_perceptron():\n",
    "    \n",
    "    # Load the model\n",
    "    model = load_model('idsmodel')\n",
    "    \n",
    "    print(\"Extracting labels...\")\n",
    "    # Prepare data( extract classes in order to turn to nominal ) \n",
    "    label_classes,nominal_cols,columns = transform_to_nominal()\n",
    "    \n",
    "    print(\"Features we willl use: \\n\"+str(columns))\n",
    "    cols = ['dur','proto','service','state','spkts','dpkts','rate','sttl','dttl','sload','dload','sintpkt','dintpkt','sjit','djit','swin','stcpb','dtcpb','tcprtt','smeansz','dmeansz','trans_depth','response_body_len','ct_srv_src','ct_state_ttl','ct_dst_ltm','is_ftp_login','ct_flw_http_mthd']\n",
    "   \n",
    "    print(\"\\n\\nStarting the real time NIDS....\\n\\n\")\n",
    "    # Read the line\n",
    "    firstLine = input()\n",
    "\n",
    "    #GLOBAL VARIABLES\n",
    "    ct_srv = 0\n",
    "    ct_flow = 0 \n",
    "    ct_dst = 0\n",
    "    while True:\n",
    "\n",
    "      if \"Dur\" not in firstLine: \n",
    "        secLine = input()\n",
    "        \n",
    "        # Retrieve the tokens of the two lines\n",
    "        firstLine_tokens,firstSrcIP,firstSrcPort,firstDstIP,firstDstPort,firstLtime,first_bd_len =basic_tokens(firstLine)\n",
    "        secLine_tokens,secSrcIP,secSrcPort,secDstIP,secDstPort,secLtime,sec_bd_len = basic_tokens(secLine)\n",
    "        \n",
    "        # Response boby length ( We need to fix that shit )\n",
    "        firstLine_tokens.insert(22,first_bd_len)\n",
    "\n",
    "        #Check for the ct_srv \n",
    "        ct_srv = ct_srv_src(firstSrcIP,firstLine_tokens[2],secSrcIP,secLine_tokens[2],ct_srv)\n",
    "        firstLine_tokens.insert(23,str(ct_srv))\n",
    "        \n",
    "        #Check for the ct_dst_lt \n",
    "        ct_dst = ct_dst_ltm(firstDstIP,firstLtime,secDstIP,secLtime,ct_dst)\n",
    "        firstLine_tokens.insert(25,str(ct_dst))        \n",
    "\n",
    "        #Check ct_flw_http_mthd\n",
    "        ct_flow = ct_flw_http_mthd(firstSrcIP,firstDstIP,firstSrcPort,firstDstPort,secSrcIP,secDstIP,secSrcPort,secDstPort,firstLine_tokens[2],ct_flow)\n",
    "        firstLine_tokens.insert(len(firstLine_tokens)+1,str(ct_flow))\n",
    "        \n",
    "        firstLine_tokens = np.array([firstLine_tokens])\n",
    "        df = pd.DataFrame(columns=cols,data=firstLine_tokens)\n",
    "        keepDF = df.copy()\n",
    "        \n",
    "        # Turn from nominal to numeric\n",
    "        for nom in nominal_cols:\n",
    "\n",
    "          le = LabelEncoder()\n",
    "          le.fit(df[nom])\n",
    "          \n",
    "          # Check if the classes already included to the encoder\n",
    "          if le.classes_[0] not in label_classes[nom]:\n",
    "            le.classes_ = np.concatenate((label_classes[nom],le.classes_))\n",
    "          else:\n",
    "            le.classes_ = label_classes[nom]\n",
    "\n",
    "          # Transform the nominal to numberic\n",
    "          df[nom] = le.transform(df[nom])\n",
    "\n",
    "        # String to numbers\n",
    "        dataForTest = np.array(df)[0]\n",
    "        dataForTest = np.array([float(it) for it in dataForTest])\n",
    "        \n",
    "        # Predict\n",
    "        scaler = MinMaxScaler(feature_range=(0, 1))\n",
    "        dataForTest = scaler.fit_transform(dataForTest.reshape(-1,1))\n",
    "\n",
    "        dataForTest = dataForTest.reshape(1,28)\n",
    "        ypred = model.predict(dataForTest)\n",
    "        ypred = np.argmax(ypred,axis=1)\n",
    "\n",
    "        classes = ['Analysis','Backdoor','DoS','Exploits','Fuzzers','Generic','Normal','Reconnaissance','Shellcode','Worms']\n",
    "\n",
    "        if ypred[0] == 6:\n",
    "          print(bcolors.OKGREEN+\"Normal Behavior\"+bcolors.ENDC)\n",
    "        else:\n",
    "          print(bcolors.FAIL+\"Possible '\" + classes[ypred[0]] + \"' Attack : added to out.csv for analysis.\" + bcolors.ENDC)\n",
    "          if path.exists('out.csv'):\n",
    "            pd.DataFrame(dataForTest).to_csv('out.csv',mode='a', header=False)\n",
    "          else:\n",
    "            pd.DataFrame(dataForTest).to_csv('out.csv')\n",
    "        #predictions = np.argmax(ypreds, axis=1)\n",
    "        firstLine = secLine\n",
    "      else:\n",
    "        secLine = input() \n",
    "        firstLine = secLine"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
